﻿using Commons.Responses;
using DomainCommons.Models;
using ORM;
using System.Linq.Expressions;

namespace IRepositories
{
    public interface IBaseRepository<T, TEntity>
       where TEntity : class, IEntity<T>, new()
    {
        PSPDbContext Context { get; }
        #region 1. 查询库存数量相关的方法
        /// <summary>
        /// 根据 Id 查找对应的领域泛型对象领域对象是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<bool> HasAsync(T id);
        /// <summary>
        /// 根据条件查找是否存在
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        Task<bool> AnyAsync(Expression<Func<TEntity, bool>> predicate);
        #endregion
        #region 2. 查询特定库存对象的方法
        /// <summary>
        /// 根据 Id 获取单个领域泛型对象的仓储数据
        /// </summary>
        /// <param name="id">待查询领域泛型对象的 Id</param>
        /// <returns></returns>
        Task<TEntity> GetAsync(T id);

        /// <summary>
        /// 根据查询条件，获取单个领域泛型对象的领域对象仓储数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate);
        #endregion
        #region 3. 查询特定库存对象集合的方法
        /// <summary>
        /// 获取仓储中所有的领域泛型对象领域对象集合
        /// </summary>
        /// <returns></returns>
        Task<DatasResponse<TEntity>> GetAllAsync();
        //Task<List<TDdo>> GetAllAsync();
        /// <summary>
        /// 根据查询条件，获取仓储中满足条件的领域泛型对象领域对象集合,排序true为降序
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderByFields"></param>
        /// <returns></returns>
        Task<DatasResponse<TEntity>> GetAllAsync(Expression<Func<TEntity, bool>> predicate, Dictionary<string, bool> orderByFields = null);
        /// <summary>
        /// 根据查询条件，获取仓储中满足条件，并且按照起始索引、数量返回的领域对象集合
        /// </summary>
        /// /// <param name="pageIndex">起始索引</param>
        /// <param name="pageSize">数量</param>
        /// <param name="predicate">查询条件表达式</param>
        /// <returns></returns>
        Task<DatasResponse<TEntity>> GetBySelectAsync(int pageIndex, int pageSize, Expression<Func<TEntity, bool>> predicate);
        /// <summary>
        /// 其他类型的数据
        /// </summary>
        /// <typeparam name="Tid"></typeparam>
        /// <typeparam name="Other"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<DataResponse<Other>> GetOtherByIdAsync<Tid, Other>(Tid id) where Other : class, IEntity<Tid>, new();
        Task<DataResponse<Other>> GetOtherAsync<Tid, Other>(Expression<Func<Other, bool>> predicate) where Other : class, IEntity<Tid>, new();

        #endregion
        #region 4. 入库的方法
        /// <summary>
        /// 入库：将传入的领域泛型对象领域对象添加到仓储中
        /// </summary>
        /// <param name="bo"></param>
        /// <returns></returns>
        Task<DataResponse<TEntity>> AddAsync(TEntity bo);
        /// <summary>
        /// 新增其他类型的数据
        /// </summary>
        /// <typeparam name="Tid"></typeparam>
        /// <typeparam name="Other"></typeparam>
        /// <param name="oher"></param>
        /// <returns></returns>

        Task<MessageResponse> AddOtherAsync<Tid, Other>(Other oher) where Other : class, IEntity<Tid>, new();
        #endregion
        #region 5. 更新库存对象的方法
        /// <summary>
        /// 更新（注意不是更换）：使用传入的领域泛型对象领域对象，更新仓储中已经存在的领域泛型对象领域对象的值
        /// </summary>
        /// <param name="bo"></param>
        /// <returns></returns>
        Task<MessageResponse> UpdateAsync(TEntity bo);
        Task<MessageResponse> UpdateOtherAsync<Tid, Other>(Other oher) where Other : class, IEntity<Tid>, new();
        #endregion

        #region 6. 清除库存对象的方法
        /// <summary>
        /// 报废清除出库：根据领域泛型对象领域对象的特征值（这里是 Id），删除仓储中的领域泛型对象对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<MessageResponse> DeleteAsync(T id);
        Task<MessageResponse> DeleteRangeAsync(List<TEntity> bos);
        Task<MessageResponse> DeleteRangeByIdAsync(List<T> ids);
        Task<MessageResponse> SoftDeleteAsync(T id);
        Task<MessageResponse> SoftDeleteRangeByIdAsync(List<T> ids);
        #endregion
    }
}
